package com.ljfresh.customer.sercice.Impl;

import com.ljfresh.customer.sercice.TwiterIdService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.text.DecimalFormat;

/**
 * Created by Administrator on 2017/5/23.
 */
@Service
public class TwiterIdServiceImpl implements TwiterIdService {

    @Value("${twiterid}")
    private Integer node;

    public static final int NODE_SHIFT = 10;
    public static final int SEQ_SHIFT = 12;

    //随机数
    public static final short MAX_NODE = 1024;
    public static final short MAX_SEQUENCE = 4096;

    private short sequence;
    private long referenceTime;

    //顺序位数
    DecimalFormat df4 = new DecimalFormat("0000");
    public static final short MAX_4_RANK = 9999;
    private short sequence4;
    DecimalFormat df6 = new DecimalFormat("000000");
    public static final int MAX_6_RANK = 999999;
    private int sequence6;

    /**
     * Generates a k-ordered unique 64-bit integer. Subsequent invocations of this method will produce
     * increasing integer values.
     *
     * @return The next 64-bit integer.
     */
    public synchronized long next() {

        long currentTime = System.currentTimeMillis();
        long counter;

        synchronized (this) {

            if (currentTime < referenceTime) {
                throw new RuntimeException(String.format("Last referenceTime %s is after reference time %s", referenceTime, currentTime));
            } else if (currentTime > referenceTime) {
                this.sequence = 0;
            } else {
                if (this.sequence < MAX_SEQUENCE) {
                    this.sequence++;
                } else {
                    throw new RuntimeException("Sequence exhausted at " + this.sequence);
                }
            }
            counter = this.sequence;
            referenceTime = currentTime;
        }

        return currentTime << NODE_SHIFT << SEQ_SHIFT | node << SEQ_SHIFT | counter;
    }

    public Long getTwiterId() {
        return next();
    }

    @Override
    public String getRankInt4() {
        synchronized (this) {
            if (this.sequence4 < MAX_4_RANK) {
                this.sequence4++;
            } else {
                this.sequence4 = 0;
            }
            return df4.format(this.sequence4);
        }
    }

    @Override
    public String getRankInt6() {
        synchronized (this) {
            if (this.sequence6 < MAX_6_RANK) {
                this.sequence6++;
            } else {
                this.sequence6 = 0;
            }
        }
        return df6.format(this.sequence6);
    }

    @Override
    public String getSessionId() {
        return "user_session" + next();
    }

}
